package transport

import (
	"context"
	"rpcdemo/endpoint"
	"rpcdemo/pb"
	"rpcdemo/service"

	grpctransport "github.com/go-kit/kit/transport/grpc"
)

type gRPCServer struct {
	pb.UnimplementedDemoServer
	sum    grpctransport.Handler
	concat grpctransport.Handler
}

func NewGRPCServer(svc service.Service) pb.DemoServer {
	return &gRPCServer{
		sum: grpctransport.NewServer(
			endpoint.MakeSumEndpoint(svc),
			DecodeSumRequest,
			EncodeSumResponse,
		),
		concat: grpctransport.NewServer(
			endpoint.MakeConcatEndpoint(svc),
			DecodeConcatRequest,
			EncodeConcatResponse,
		),
	}
}

func (s *gRPCServer) Sum(ctx context.Context, req *pb.SumRequest) (*pb.SumResponse, error) {
	_, res, err := s.sum.ServeGRPC(ctx, req)
	if err != nil {
		return nil, err
	}

	return res.(*pb.SumResponse), nil
}

func (s *gRPCServer) Concat(ctx context.Context, req *pb.ConcatRequest) (*pb.ConcatResponse, error) {
	_, res, err := s.concat.ServeGRPC(ctx, req)
	if err != nil {
		return nil, err
	}

	return res.(*pb.ConcatResponse), nil
}

func DecodeSumRequest(_ context.Context, r interface{}) (interface{}, error) {
	req := r.(*pb.SumRequest)
	return endpoint.SumRequest{A: req.A, B: req.B}, nil
}

func EncodeSumResponse(_ context.Context, r interface{}) (interface{}, error) {
	res := r.(endpoint.SumResponse)
	return &pb.SumResponse{Result: res.Result, Err: res.Err}, nil
}

func DecodeConcatRequest(_ context.Context, r interface{}) (interface{}, error) {
	req := r.(*pb.ConcatRequest)
	return req, nil
}

func EncodeConcatResponse(_ context.Context, r interface{}) (interface{}, error) {
	res := r.(endpoint.ConcatResponse)
	return &pb.ConcatResponse{Result: res.Result, Err: res.Err}, nil
}
